﻿using FlyingEye.Application.Exceptions;
using FlyingEye.DeviceClients;
using FlyingEye.DeviceClients.Requests;
using FlyingEye.DeviceClients.Responses;
using FlyingEye.Exceptions;
using FlyingEyeClient.ApplicationServices.SignalRHubs;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace FlyingEye
{
    /// <summary>
    /// 应用程序
    /// </summary>
    public class FlyingEyeClientApplication
    {
        private readonly ILogger<FlyingEyeClientApplication> _logger;

        private readonly ApplicationOptions _applicationOptions;

        public ApplicationContext Context { get; }

        public DeviceManager DeviceManager => Context.DeviceManager;

        public SignalRClient SignalRClient => Context.SignalRClient;

        public IDeviceClient DeviceClient { get; }

        public FlyingEyeClientApplication(
            IOptions<ApplicationOptions> options,
            ApplicationContext context,
            SignalRClient signalRClient,
            DeviceManager deviceManager,
            IDeviceClient deviceClient,
            ILogger<FlyingEyeClientApplication> logger)
        {
            _applicationOptions = options.Value;
            Context = context;
            Context.DeviceManager = deviceManager;
            Context.SignalRClient = signalRClient;
            DeviceClient = deviceClient;
            _logger = logger;
        }

        public bool Is { get; set; }

        /// <summary>
        /// 开启应用程序
        /// </summary>
        public async Task OpenAsync(string resourceId)
        {
            Context.ResourceId = resourceId;
            var url = _applicationOptions.HttpBaseUrl + $"/device-hub";

            // 连接 SignalR
            try
            {
                await SignalRClient.ConnectAsync(url, resourceId);
                // 注册所有方法
                RegisterMethods();
            }
            catch (Exception ex)
            {
                throw new SignalRConnectionException(ex);
            }

            // 连接设备
            try
            {
                await DeviceManager.ConnectAsync(resourceId);
            }
            catch (DeviceConnectAggregateException ex)
            {
                _logger.LogError(ex, ex.Message);
                // 设备连接失败，不用断开连接
            }
            catch (Exception)
            {
                // 连接设备错误，断开 SignalR 连接
                await SignalRClient.DisconnectAsync();
                throw;
            }
        }

        private void RegisterMethods()
        {
            SignalRClient.On((hubConnection) =>
            {
                hubConnection.On("ConfigAsync", async ()
                    => await DeviceClient.ConfigAsync());
                hubConnection.On<WriteValueRequest, DefaultResponse>("WriteValueAsync", async (request)
                    => await DeviceClient.WriteValueAsync(request));
                hubConnection.On<ReadStringValueRequest, ReadValueResponse>("ReadStringValueAsync", async (request)
                    => await DeviceClient.ReadStringValueAsync(request));
                hubConnection.On<ReadNumericValueRequest, ReadValueResponse>("ReadNumericValueAsync", async (request)
                    => await DeviceClient.ReadNumericValueAsync(request));
            });
        }

        /// <summary>
        /// 关闭应用程序
        /// </summary>
        public async Task CloseAsync()
        {
            await SignalRClient.DisconnectAsync();
            await DeviceManager.CloseAllAsync();
        }
    }
}
